package cn.wonhigh.o2o.openfire.plugins.util;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisConnectionException;

/**
 * Redis相关的功能模板类.引用自portal-server
 * 
 * @author wei.ss
 * @createDate 2015-03-09
 * @version 1.0
 */
public class RedisTemplate {
	private static final Logger LOG = LoggerFactory
			.getLogger(RedisTemplate.class);
	private JedisPool redisPool;

	public void setRedisPool(JedisPool redisPool) {
		this.redisPool = redisPool;
	}

	public boolean exists(String key) {
		Jedis jedis = redisPool.getResource();
		boolean result = false;
		try {
			result = jedis.exists(key);
		} catch (JedisConnectionException e) {
			if (null != jedis) {
				redisPool.returnBrokenResource(jedis);
				jedis = null;
			}
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
		return result;
	}

	public void push(String queueName, String content) {
		Jedis jedis = redisPool.getResource();
		try {
			jedis.lpush(queueName, content);
		} catch (JedisConnectionException e) {
			if (null != jedis) {
				redisPool.returnBrokenResource(jedis);
				jedis = null;
			}
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
	}

	public void set(String key, String value) {
		Jedis jedis = redisPool.getResource();
		try {
			jedis.set(key, value);
		} catch (JedisConnectionException e) {
			if (null != jedis) {
				redisPool.returnBrokenResource(jedis);
				jedis = null;
			}
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
	}

	public void setex(String key, String value, int timeout) {
		Jedis jedis = redisPool.getResource();
		try {
			jedis.setex(key, timeout, value);
		} catch (JedisConnectionException e) {
			if (null != jedis) {
				redisPool.returnBrokenResource(jedis);
				jedis = null;
			}
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
	}
	
	public long setnx(String key, String value) {
		Jedis jedis = redisPool.getResource();
		long result = 0;
		try {
			result = jedis.setnx(key, value);
		} catch (JedisConnectionException e) {
			if (null != jedis) {
				redisPool.returnBrokenResource(jedis);
				jedis = null;
			}
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
		return result;
	}

	public String get(String key) {
		Jedis jedis = redisPool.getResource();
		String value = "";
		try {
			value = jedis.get(key);
		} catch (JedisConnectionException e) {
			if (null != jedis) {
				redisPool.returnBrokenResource(jedis);
				jedis = null;
			}
		} catch (Exception e) {
			LOG.error("调用Redis出现异常", e);
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
		return value;
	}

	public String getAndDel(String key) {
		Jedis jedis = redisPool.getResource();
		String value = "";
		try {
			value = jedis.get(key);
			jedis.del(key);
		} catch (JedisConnectionException e) {
			if (null != jedis) {
				redisPool.returnBrokenResource(jedis);
				jedis = null;
			}
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
		return value;
	}

	public void del(String key) {
		Jedis jedis = redisPool.getResource();
		try {
			jedis.del(key);
		} catch (JedisConnectionException e) {
			if (null != jedis) {
				redisPool.returnBrokenResource(jedis);
				jedis = null;
			}
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
	}

	public List<String> lRange(String key) {
		List<String> result = new ArrayList<String>();
		Jedis jedis = redisPool.getResource();
		try {
			result = jedis.lrange(key, 0, -1);
			return result;
		} catch (Exception e) {
			LOG.error("调用Redis出现异常", e);
			return null;
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
	}

	/**
	 * @category 使用无序的Set
	 * @param key
	 * @param score
	 * @param member
	 * @return
	 */
	public Long sAdd(String key, String... members) {
		Long result = null;
		Jedis jedis = redisPool.getResource();
		try {
			if (members != null && members.length > 0) {
				result = jedis.sadd(key, members);
			}
			return result;
		} catch (Exception e) {
			LOG.error("调用Redis出现异常", e);
			return null;
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
	}

	/**
	 * @category 弹出集合
	 * @param key
	 * @return
	 */
	public Set<String> sMembers(String key) {
		Set<String> result = new HashSet<String>();
		Jedis jedis = redisPool.getResource();
		try {
			result = jedis.smembers(key);
			return result;
		} catch (Exception e) {
			LOG.error("调用Redis出现异常", e);
			return null;
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
	}

	/**
	 * @category 删除集合中的元素
	 * @param key
	 * @param members
	 * @return
	 */
	public Long sRem(String key, String... members) {
		Long result = null;
		Jedis jedis = redisPool.getResource();
		try {
			if (members != null && members.length > 0) {
				result = jedis.srem(key, members);
			}
			return result;
		} catch (Exception e) {
			LOG.error("调用Redis出现异常", e);
			return null;
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
	}

	/**
	 * @category 返回多个key值集合的交集
	 * @param keys
	 * @return
	 */
	public Set<String> sInter(String... keys) {
		Set<String> result = new HashSet<String>();
		Jedis jedis = redisPool.getResource();
		try {
			result = jedis.sinter(keys);
			return result;
		} catch (Exception e) {
			LOG.error("调用Redis出现异常", e);
			return null;
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
	}

	/**
	 * @category 返回多个key值集合的并集
	 * @param keys
	 * @return
	 */
	public Set<String> sUnion(String... keys) {
		Set<String> result = new HashSet<String>();
		Jedis jedis = redisPool.getResource();
		try {
			result = jedis.sunion(keys);
			return result;
		} catch (Exception e) {
			LOG.error("调用Redis出现异常", e);
			return null;
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
	}

	/**
	 * @category 设置键的保存时间
	 * @param key
	 * @param seconds
	 * @return
	 */
	public Long expire(String key, int seconds) {
		Long result = null;
		Jedis jedis = redisPool.getResource();
		try {
			result = jedis.expire(key, seconds);
			return result;
		} catch (Exception e) {
			LOG.error("调用Redis出现异常", e);
			return null;
		} finally {
			if (null != jedis) {
				redisPool.returnResource(jedis);
			}
		}
	}

	/**
	 * 设置redis同步锁
	 * 
	 * @param key
	 * @param timeout
	 */
	public void lock(String key, int timeout) {
		Jedis jedis = null;
		try {
			jedis = redisPool.getResource();
			do {
				// setnx保证原子操作
				long i = jedis.setnx(key, key);
				if (i == 1) {
					if (timeout > 0) {
						jedis.expire(key, timeout);
					}
					break;
				}
				Thread.sleep(50);
			} while (true);
		} catch (JedisConnectionException je) {
			LOG.error(je.getMessage(), je);
			if (jedis != null) {
				redisPool.returnBrokenResource(jedis);
			}
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		} finally {
			if (jedis != null) {
				redisPool.returnResource(jedis);
			}
		}
	}

	/**
	 * 设置同步锁
	 * 
	 * @param key
	 */
	public void lock(String key) {
		lock(key, 0);
	}

	/**
	 * 释放锁
	 * 
	 * @param key
	 */
	public void unlock(String key) {
		del(key);
	}
}
